//
//  WebDetailViewController.swift
//  CodingTest
//
//  Created by LYPC on 2021/11/19.
//

import UIKit
import WebKit

struct WebDetailParam: RouterParam {
    var urlStr: String
    var title: String
    
    init(urlStr: String, title: String = "") {
        self.urlStr = urlStr
        self.title = title
    }
}

extension WebDetailViewController: Routable {
    static func initWithRouter(params: RouterParam?) -> UIViewController? {
        guard let data = params as? WebDetailParam
        else { k_log("🔴 error init \(self) by illegal params"); return nil }
        return WebDetailViewController(initData: data)
    }
}

final class WebDetailViewController: BaseViewController {
    
    private var initData: WebDetailParam
    init(initData: WebDetailParam) {
        self.initData = initData
    }
    
    let webView = BaseWebView()
    private let progressView = UIProgressView(progressViewStyle: .default)
    
    // MARK: view cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        setupStyle()
        setupLayout()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        view.endEditing(true)
    }
    
    deinit {
        webView.removeObserver(self, forKeyPath: "canGoBack")
        webView.removeObserver(self, forKeyPath: "estimatedProgress")
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "canGoBack" {
            if webView.canGoBack {
                self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
            } else {
                self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
            }
        } else if keyPath == "estimatedProgress" {
            progressView.alpha = CGFloat(1.0 - webView.estimatedProgress) + 0.2
            let progerss = max(Float(webView.estimatedProgress), 0.1)
            progressView.setProgress(progerss, animated: true)
            if webView.estimatedProgress >= 1.0 {
                kDelay(0.3) {
                    self.progressView.alpha = 0.0
                    self.progressView.setProgress(0.0, animated: false)
                }
            }
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
}

// MARK: - ********* webview delegate
extension WebDetailViewController: WKNavigationDelegate {
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        webView.evaluateJavaScript(
            "document.getElementsByTagName('body')[0].style.background='#FAFAFA'",
            completionHandler: nil)
    }
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
//        k_log("==== error: \(error)")
    }
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
//        k_log("==== error: \(error)")
    }
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if (navigationAction.targetFrame == nil) {
            webView.load(navigationAction.request)
        }
        guard let policy = WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2)
            else { decisionHandler(.allow); return }
        decisionHandler(policy)
    }
}

// MARK: - ********* UIResponse Funcs
extension WebDetailViewController {
    override func navleftViewTapped() {
        if webView.canGoBack {
            webView.goBack()
        } else {
            self.navigationController?.popViewController(animated: true)
        }
    }
}

// MARK: - UI Setup
private extension WebDetailViewController {
    
    func setupLayout() {
        view.addSubview(webView)
        webView.addSubview(progressView)
    
        webView.snp.makeConstraints { (m) in
            m.top.equalToSuperview().inset(kNavBtm)
            m.bottom.equalToSuperview()
            m.leading.trailing.equalToSuperview()
        }
        progressView.snp.makeConstraints { (m) in
            m.top.leading.trailing.equalToSuperview()
            m.height.equalTo(2)
        }
    }
    
    func setupStyle() {
        
        navBar.title = initData.title
        view.backgroundColor = .color(.viewBg)
        
        webView.navigationDelegate = self
        webView.uiDelegate = self
        webView.backgroundColor = .color(.viewBg)
        webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
        webView.addObserver(self, forKeyPath: "canGoBack", options: .new, context: nil)
        webView
            .evaluateJavaScript("document.getElementsByTagName('body')[0].style.background='#FAFAFA'", completionHandler: nil)
        
        /// 加载URL
        if let requestUrl = URL(string: initData.urlStr) {
            let request = URLRequest(url: requestUrl)
            webView.load(request)
        } else { return }
        
        /// 进度条
        progressView.trackTintColor = .clear
        progressView.progressTintColor = .color(.theme)
        progressView.isHidden = false
        progressView.setProgress(0.05, animated: true)
    }
}

// MARK: - WKUIDelegate 不实现该代理方法 网页内调用弹窗时会抛出异常,导致程序崩溃
extension WebDetailViewController: WKUIDelegate {
    
    // 获取js 里面的提示
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in
            completionHandler()
        }))
        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in
            completionHandler()
        }))
        self.present(alert, animated: true, completion: nil)
    }
    
    // js 信息的交流
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in
            completionHandler(true)
        }))
        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in
            completionHandler(false)
        }))
        self.present(alert, animated: true, completion: nil)
    }
    
    // 交互。可输入的文本。
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        let alert = UIAlertController(title: prompt, message: defaultText, preferredStyle: .alert)
        alert.addTextField { (textField: UITextField) -> Void in
            textField.textColor = UIColor.red
        }
        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in
            completionHandler(alert.textFields![0].text!)
        }))
        self.present(alert, animated: true, completion: nil)
    }
}
